<?php
class JWT {
    //header头部
    private static $header = [
        'alg' => 'HS256',     // 声明加密的算法 通常直接使用 HMAC SHA256
        'typ' => 'JWT',        // 声明类型
    ];

    //secret密钥
    private static $secret = 123456;

    /**
     * 生成签名
     * @param array $payload 载荷
     * @return array            返回结果
     */
    public static function getToken(array $payload) {
        if (!is_array($payload)) {
            return ['status' => 0, 'msg' => '参数错误'];
        }

        //头部
        $base_header = base64_encode(json_encode(self::$header));
        //载荷
        $base_payload = base64_encode(json_encode($payload));
        //签证：header连接payload
        $sign = self::signature($base_header . $base_payload, self::$secret);

        //拼接成token
        $token = $base_header . '.' . $base_payload . '.' . $sign;

        return ['status' => 1, 'msg' => '签名成功', 'data' => ['token' => $token]];
    }

    /**
     * 验证签名
     * @param $token    签名token
     * @return array    返回结果
     */
    public static function verifyToken($token) {
        //字符串转数组
        $tokens = explode('.', $token);
        if (count($tokens) != 3) {
            return ['status' => 0, 'msg' => '字节数不对'];
        }

        //变量赋值
        list($base_header, $base_payload, $base_sign) = $tokens;

        //header头部
        $base_header_verify = json_decode(base64_decode($base_header),true);
        if (empty($base_header_verify['alg'])) {
            return ['status' => 0, 'msg' => 'alg不存在'];
        }

        //验证payload
        $base_payload_verify = json_decode(base64_decode($base_payload),true);
        if (!isset($base_payload_verify['iat']) || $base_payload_verify['iat'] > time()) {
            return ['status' => 0, 'msg' => '签发时间大于当前服务器时间验证失败'];
        }
        if (!isset($base_payload_verify['exp']) || $base_payload_verify['exp'] < time()) {
            return ['status' => 0, 'msg' => '签名过期'];
        }

        //验证签证
        $sign = self::signature($base_header . $base_payload, self::$secret);
        if ($base_sign != $sign) {
            return ['status' => 0, 'msg' => '验证失败'];
        }

        return ['status' => 1, 'msg' => '验证通过'];
    }

    /**
     * 签证
     * @param $input        header和payload
     * @param $secret       密钥
     * @param string $alg 加密方式
     * @return string       返回签证字符串
     */
    public static function signature($input, $secret, $alg = 'HS256') {
        $sign_md5 = $input . $secret . $alg;
        return sha1($sign_md5);
    }
}